/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 *
 * Version: 5.8.2 (2021-06-23)
 */
(function () {
  'use strict'

  var global = tinymce.util.Tools.resolve('tinymce.PluginManager')

  var global$1 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils')

  var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools')

  var allowHtmlInNamedAnchor = function (editor) {
    return editor.getParam('allow_html_in_named_anchor', false, 'boolean')
  }

  var namedAnchorSelector = 'a:not([href])'
  var isEmptyString = function (str) {
    return !str
  }
  var getIdFromAnchor = function (elm) {
    var id = elm.getAttribute('id') || elm.getAttribute('name')
    return id || ''
  }
  var isAnchor = function (elm) {
    return elm && elm.nodeName.toLowerCase() === 'a'
  }
  var isNamedAnchor = function (elm) {
    return isAnchor(elm) && !elm.getAttribute('href') && getIdFromAnchor(elm) !== ''
  }
  var isEmptyNamedAnchor = function (elm) {
    return isNamedAnchor(elm) && !elm.firstChild
  }

  var removeEmptyNamedAnchorsInSelection = function (editor) {
    var dom = editor.dom
    global$1(dom).walk(editor.selection.getRng(), function (nodes) {
      global$2.each(nodes, function (node) {
        if (isEmptyNamedAnchor(node)) {
          dom.remove(node, false)
        }
      })
    })
  }
  var isValidId = function (id) {
    return /^[A-Za-z][A-Za-z0-9\-:._]*$/.test(id)
  }
  var getNamedAnchor = function (editor) {
    return editor.dom.getParent(editor.selection.getStart(), namedAnchorSelector)
  }
  var getId = function (editor) {
    var anchor = getNamedAnchor(editor)
    if (anchor) {
      return getIdFromAnchor(anchor)
    } else {
      return ''
    }
  }
  var createAnchor = function (editor, id) {
    editor.undoManager.transact(function () {
      if (!allowHtmlInNamedAnchor(editor)) {
        editor.selection.collapse(true)
      }
      if (editor.selection.isCollapsed()) {
        editor.insertContent(editor.dom.createHTML('a', { id: id }))
      } else {
        removeEmptyNamedAnchorsInSelection(editor)
        editor.formatter.remove('namedAnchor', null, null, true)
        editor.formatter.apply('namedAnchor', { value: id })
        editor.addVisual()
      }
    })
  }
  var updateAnchor = function (editor, id, anchorElement) {
    anchorElement.removeAttribute('name')
    anchorElement.id = id
    editor.addVisual()
    editor.undoManager.add()
  }
  var insert = function (editor, id) {
    var anchor = getNamedAnchor(editor)
    if (anchor) {
      updateAnchor(editor, id, anchor)
    } else {
      createAnchor(editor, id)
    }
    editor.focus()
  }

  var insertAnchor = function (editor, newId) {
    if (!isValidId(newId)) {
      editor.windowManager.alert('Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.')
      return false
    } else {
      insert(editor, newId)
      return true
    }
  }
  var open = function (editor) {
    var currentId = getId(editor)
    editor.windowManager.open({
      title: 'Anchor',
      size: 'normal',
      body: {
        type: 'panel',
        items: [{
          name: 'id',
          type: 'input',
          label: 'ID',
          placeholder: 'example'
        }]
      },
      buttons: [
        {
          type: 'cancel',
          name: 'cancel',
          text: 'Cancel'
        },
        {
          type: 'submit',
          name: 'save',
          text: 'Save',
          primary: true
        }
      ],
      initialData: { id: currentId },
      onSubmit: function (api) {
        if (insertAnchor(editor, api.getData().id)) {
          api.close()
        }
      }
    })
  }

  var register = function (editor) {
    editor.addCommand('mceAnchor', function () {
      open(editor)
    })
  }

  var isNamedAnchorNode = function (node) {
    return node && isEmptyString(node.attr('href')) && !isEmptyString(node.attr('id') || node.attr('name'))
  }
  var isEmptyNamedAnchorNode = function (node) {
    return isNamedAnchorNode(node) && !node.firstChild
  }
  var setContentEditable = function (state) {
    return function (nodes) {
      for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i]
        if (isEmptyNamedAnchorNode(node)) {
          node.attr('contenteditable', state)
        }
      }
    }
  }
  var setup = function (editor) {
    editor.on('PreInit', function () {
      editor.parser.addNodeFilter('a', setContentEditable('false'))
      editor.serializer.addNodeFilter('a', setContentEditable(null))
    })
  }

  var registerFormats = function (editor) {
    editor.formatter.register('namedAnchor', {
      inline: 'a',
      selector: namedAnchorSelector,
      remove: 'all',
      split: true,
      deep: true,
      attributes: { id: '%value' },
      onmatch: function (node, _fmt, _itemName) {
        return isNamedAnchor(node)
      }
    })
  }

  var register$1 = function (editor) {
    editor.ui.registry.addToggleButton('anchor', {
      icon: 'bookmark',
      tooltip: 'Anchor',
      onAction: function () {
        return editor.execCommand('mceAnchor')
      },
      onSetup: function (buttonApi) {
        return editor.selection.selectorChangedWithUnbind('a:not([href])', buttonApi.setActive).unbind
      }
    })
    editor.ui.registry.addMenuItem('anchor', {
      icon: 'bookmark',
      text: 'Anchor...',
      onAction: function () {
        return editor.execCommand('mceAnchor')
      }
    })
  }

  function Plugin () {
    global.add('anchor', function (editor) {
      setup(editor)
      register(editor)
      register$1(editor)
      editor.on('PreInit', function () {
        registerFormats(editor)
      })
    })
  }

  Plugin()
}())
